package com.shujia.mllib

import org.apache.spark.ml.classification.{LogisticRegression, LogisticRegressionModel}
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object Demo02Person {
  def main(args: Array[String]): Unit = {
    // 基于人体指标数据熟悉机器学习的一般流程
    val spark: SparkSession = SparkSession
      .builder()
      .master("local[*]")
      .appName("Demo02Person")
      .getOrCreate()

    import spark.implicits._

    // 1、加载数据 对数据进行数据特征工程处理
    val libsvmDF: DataFrame = spark
      .read
      .format("libsvm")
      .option("numFeatures", "10")
      .load("spark/data/mllib/data/人体指标.txt")

    // 2、将数据分为训练集以及测试集
    val randomSplitArr: Array[DataFrame] = libsvmDF.randomSplit(Array(0.8, 0.2))
    val trainDF: DataFrame = randomSplitArr(0)
    val testDF: DataFrame = randomSplitArr(1)

    testDF.printSchema()

    // 3、基于数据选择合适的算法，再确定模型
    /**
     * 如何选择合适的算法？
     * 观察数据，看有无Label
     * 有 -> 有监督学习 -> Label是连续的还是离散的？
     * 连续的 -> 回归
     * 离散的 -> 分类
     * 无 -> 无监督学习 -> 聚类
     */
    // 基于人体指标数据观察后发现 是一个分类问题 而且是二分类问题 故选择 逻辑回归算法模型进行后续处理
    val lr: LogisticRegression = new LogisticRegression()
      .setMaxIter(10)
      .setRegParam(0.3)
      .setElasticNetParam(0.8)

    // 4、将训练集带入模型 进行训练
    val lRModel: LogisticRegressionModel = lr.fit(trainDF)

    // 5、将测试集带入模型 进行预测
    val predictionDF: DataFrame = lRModel.transform(testDF)
    // 6、基于预测的结果 评估模型
    // 准确率: 预测准确地/总的数据条数
    println(s"模型的准确率为：${predictionDF.where($"label" === $"prediction").count().toDouble / predictionDF.count()}")

    // 7、如果模型通过了评估，即可将其保存起来 下次可以直接调用
    lRModel.save("spark/data/mllib/person")


  }

}
